﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Build.Client;

namespace BDV.TfsCustomActivities.BuildTasks
{
    /// <summary>
    /// Activity that change the build's part of the version in provided files.
    /// Activité qui modifie le numéro de version des assembly et fichiers (si activé)
    /// </summary>
    [BuildActivity(HostEnvironmentOption.All)]
    public sealed class IncrementAssemblyVersions : CodeActivity
    {
        private string[] AssemblyInfoAttributes = new string[] { "AssemblyVersion", "AssemblyFileVersion" };

        /// <summary>
        /// List of files to change the versions
        /// </summary>
        [RequiredArgument]
        public InArgument<List<string>> AssemblyInfoFiles { get; set; }

        /// <summary>
        /// Kind of change. Voir <see cref="AutoIncrementMode"/>
        /// </summary>
        [RequiredArgument]
        public InArgument<AutoIncrementMode> Mode { get; set; }

        /// <summary>
        /// Change set id that invoke the build.
        /// (used if <see cref="Mode"/> ==  <see cref="AutoIncrementMode.PushTfsChangeset"/>
        /// </summary>
        [RequiredArgument]
        public InArgument<string> ChangeSetNumber { get; set; }

        // If your activity returns a value, derive from CodeActivity<TResult>
        // and return the value from the Execute method.
        protected override void Execute(CodeActivityContext context)
        {
            // Obtain the runtime value of the Text input argument
            //string assemblyInfoFileMask = context.GetValue(this.AssemblyInfoFileMask);
            //string sourcesDirectory = context.GetValue(this.SourcesDirectory);

            string changeSetNumber = context.GetValue(this.ChangeSetNumber);
            AutoIncrementMode mode = context.GetValue(this.Mode);
            List<string> assemblyInfoFiles = context.GetValue(this.AssemblyInfoFiles);

            if (mode == AutoIncrementMode.None || assemblyInfoFiles == null || !assemblyInfoFiles.Any())
                return;

            // Search for AssemblyInfo files
            foreach (var file in assemblyInfoFiles) //Directory.EnumerateFiles(sourcesDirectory, assemblyInfoFileMask, SearchOption.AllDirectories))
            {
                var changed = false;

                // Get file content
                string text = File.ReadAllText(file);
                var extractInt = new Regex(@"(?<num>\d+)");
                // Search for defined attributes...
                
                foreach (var attribute in AssemblyInfoAttributes)
                {
                    //                   AssemblyVersion\(""\d+\.\d+\.\d+\.[\d\*]+""\)
                    var regex = new Regex(attribute + @"\(""\d+\.\d+\.\d+\.[\d\*]+""\)");
                    var match = regex.Match(text);
                    

                    if (match.Success)
                    {
                        int buildNumber = 1;
                        string versionNumber = match.Value.Substring(attribute.Length + 2, match.Value.Length - attribute.Length - 4);
                        var revisionIsStar = false;

                        if (versionNumber.Contains('*'))
                        {
                            versionNumber = versionNumber.Replace('*', '0');
                            revisionIsStar = true;
                        }
                        var version = new Version(versionNumber);

                        if (mode == AutoIncrementMode.Increment)
                        {
                            buildNumber = version.Build + 1;
                        }
                        else
                        {
                            buildNumber = Convert.ToInt32(extractInt.Match(changeSetNumber).Groups["num"].Value);
                        }

                        // var newVersion = new Version(version.Major, version.Minor, buildNumber, version.Revision);

                        text = regex.Replace(text, attribute + "(\"" + string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, buildNumber, revisionIsStar ? "*" : version.Revision.ToString()) + "\")");

                        // Write updated content
                        // File.WriteAllText(file, newText);
                        changed = true;
                    }
                }

                if(changed)
                    File.WriteAllText(file, text);
            }
        }
    }
}
